//---------------------------------------------------------------------------
/** 出力プラグイン管理クラス
ToDo:プラグイン関数の一対一対応だけではなく、簡単に使えるようにまとめる 
 */
//---------------------------------------------------------------------------
/*
 * Copyright (c) 1999 - 2005 shimitei
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop

#include "xpi_manage.h"

/* グローバル */
AXpiManager g_xpiManager ;
//---------------------------------------------------------------------------
/** 特に何もしないコールバック関数
 */
static int __stdcall nopXpiCallback(int nNum, int nDenom, long lData)
{
    return 0 ;
}
//---------------------------------------------------------------------------
/** デストラクタ
 * 出力プラグインを解放する
 */
AXpiManager::~AXpiManager()
{
    if ( m_xpiArray.empty() ) return ;

    std::vector<APluginABC *>::iterator ite ;
    for (ite = m_xpiArray.begin(); ite != m_xpiArray.end(); ite++)
    {
        delete *ite ;
    }
}
//---------------------------------------------------------------------------
/** 使用するプラグインをセットする
 * @param num プラグイン配列インデックス番号
 */
bool __fastcall AXpiManager::setXpi(const int num)
{
    if ( ! boundCheck( num ) ) return false ;

    m_xpi = m_xpiArray[ num ] ;
    return true ;
}
//---------------------------------------------------------------------------
/** 色深度が8bit以下で使用するプラグインをセットする
 * @param num プラグイン配列インデックス番号
 */
bool __fastcall AXpiManager::setXpi8bit(const int num)
{
    if ( ! boundCheck( num ) ) return false ;

    m_xpi8bit = m_xpiArray[ num ] ;
    return true ;
}
//---------------------------------------------------------------------------
/** 色深度が16bit以上で使用するプラグインをセットする
 * @param num プラグイン配列インデックス番号
 */
bool __fastcall AXpiManager::setXpi16bit(const int num)
{
    if ( ! boundCheck( num ) ) return false ;

    m_xpi16bit = m_xpiArray[ num ] ;
    return true ;
}
//---------------------------------------------------------------------------
/** 指定フォルダにある出力プラグインをロードする
 * @param path \\で終わるフォルダのパス
 */
void __fastcall AXpiManager::loadAll(const char *path)
{
    AnsiString findpath = (AnsiString)path + "*.xpi" ;
    loadXpi( findpath.c_str() ) ;
}
//---------------------------------------------------------------------------
/** 指定パスのプラグインをロードする
 * @param path ワイルドカード有効
 */
void __fastcall AXpiManager::loadXpi(const char *path)
{
    AnsiString xpipath ;
    AnsiString pathdir = ExtractFilePath( path ) ;

    WIN32_FIND_DATA ff ;
    HANDLE hf = FindFirstFile( path, &ff ) ;
    if ( hf == INVALID_HANDLE_VALUE ) return ;

    while ( hf != INVALID_HANDLE_VALUE )
    {
        APluginABC *xpi = new APluginABC ;
        xpipath = pathdir + ff.cFileName ;

        if ( ! xpi->load( xpipath.c_str() ) )
        {
            delete xpi ;
        }
        else
        {
            m_xpiArray.push_back( xpi ) ;
            m_xpiCount++ ;
        }
        if ( FindNextFile( hf, &ff ) == 0 ) break ;
    }
    FindClose( hf ) ;
}
//---------------------------------------------------------------------------
/** 対応している色数かチェック
 * 対応している場合は現在のプラグインにセットされる
 * @param color 色深度
 */
bool __fastcall AXpiManager::checkSupport8(const short color)
{
    int ret = 0 ;

    try
    {
        ret = m_xpi8bit->IsSupported( color ) ;
        if ( ret != 0 ) m_xpi = m_xpi8bit ;
    }
    catch (...)
    {
        //throw ;
    }

    return ret ;
}
//---------------------------------------------------------------------------
/** 対応している色数かチェック
 * 対応している場合は現在のプラグインにセットされる
 * @param color 色深度
 */
bool __fastcall AXpiManager::checkSupport16(const short color)
{
    int ret = 0 ;

    try
    {
        ret = m_xpi16bit->IsSupported( color ) ;
        if ( ret != 0 ) m_xpi = m_xpi16bit ;
    }
    catch (...)
    {
        //throw ;
    }

    return ret ;
}
//---------------------------------------------------------------------------
/** 変換して保存
 * @param filepath 変換保存先のファイルパス
 * @param flag
 * @param pHBInfo BITMAPINFOデータハンドルへのポインタ
 * @param pHBm ビットマップデータハンドルへのポインタ
 * @param lpInfo 画像のPictureInfoポインタ
 * @param lpPrgressCallback コールバック関数
 * @param lData コールバック関数に渡すデータ
 */
int __fastcall AXpiManager::convertPicture(char *filepath, const DWORD flag,
                        HANDLE *pHBInfo, HANDLE *pHBm,
                        PictureInfo *lpInfo,
                        SPI_PROGRESS lpPrgressCallback, const long lData)
{
    int ret = XPI_OTHER_ERROR ;

    try
    {
        if ( m_xpi != NULL )
        {
            if (lpPrgressCallback == NULL)
            {
                lpPrgressCallback = nopXpiCallback ;
            }
            ret = m_xpi->CreatePicture(filepath, flag,
                        pHBInfo, pHBm, lpInfo,
                        lpPrgressCallback, lData) ;
        }
    }
    catch (...)
    {
        ret = XPI_FATAL_ERR ;
        //throw ;
    }

    return ret ;
}
//---------------------------------------------------------------------------
/** 出力プラグインの情報を得る
 * @param num プラグイン配列のインデックス番号。-1の場合は現在のプラグイン
 * @param infoNum 取得する情報番号
 * @param buf 情報を書き込むバッファ
 * @param buflen bufのサイズ
 */
bool __fastcall AXpiManager::getPluginInfo(const int num, const int infoNum, const LPSTR buf, const int buflen)
{
    bool ret = false ;

    try
    {
        if (num == -1)
        {
            ret = m_xpi->GetPluginInfo( infoNum, buf, buflen ) ;
        }
        else if (setXpi(num))
        {
            ret = m_xpi->GetPluginInfo( infoNum, buf, buflen ) ;
        }
    }
    catch (...)
    {
        //throw ;
    }

    return ret ;
}
//---------------------------------------------------------------------------
/** 出力プラグインの情報を得る
 * @param num プラグイン配列のインデックス番号。-1の場合は現在のプラグイン
 * @param infoNum 取得する情報番号
 * @param buf 情報を書き込むバッファ
 * @param buflen bufのサイズ
 */
AnsiString __fastcall AXpiManager::getXpiInfo(const int num, const int infoNum)
{
    AnsiString retstr = "" ;
    const infoBufSize = 512 ;
    const buflen = infoBufSize -1 ; // プラグイン側で終端があいまいでも大丈夫
    char buf[ infoBufSize ] = "" ;

    if ( getPluginInfo( num, infoNum, buf, buflen ) )
    {
        buf[ buflen ] = '\0' ; // プラグインは信用しない
        retstr = buf ;
    }

    return retstr ;
}
//---------------------------------------------------------------------------
/** 出力プラグインの設定ダイアログを表示する
 * @param num プラグイン配列インデックス番号
 * @param parent ダイアログの親ウィンドウハンドル
 * @param func ダイアログ番号
 * @return 設定ダイアログが無い場合falseを返す
 */
bool __fastcall AXpiManager::xpiConfig(const int num, const HWND parent, const int func)
{
    try
    {
        if ( setXpi( num ) )
        {
            if ( m_xpi->ConfigurationDlg == NULL )
            {
                return false ;
            }
            else
            {
                m_xpi->ConfigurationDlg( parent, func ) ;
            }
        }
    }
    catch (...)
    {
        //throw ;
    }

    return true ;
}
//---------------------------------------------------------------------------

